using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Toolbox.DnsService.Interfaces;
using Toolbox.DnsService.Models;
using Toolbox.DnsService.Services;

namespace Toolbox.DnsService
{
    /// <summary>
    /// DNS服务控制台应用程序主程序
    /// 作者：huobing
    /// </summary>
    class Program
    {
        private static IDnsService? _dnsService;
        private static IDnsLogger? _logger;
        private static IDnsConfigManager? _configManager;
        private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
        private static CancellationTokenSource? _cancellationTokenSource;
        private static bool _isRunning = false;
        private static DnsServiceOptions _options = new DnsServiceOptions();

        /// <summary>
        /// 应用程序主入口点
        /// </summary>
        /// <param name="args">命令行参数</param>
        static void Main(string[] args)
        {
            Console.Title = "DNS Service - Toolbox";
            Console.WriteLine("=== DNS Service 启动中 ===");

            try
            {
                // 解析命令行参数
                _options = ParseCommandLineArgs(args);
                
                // 初始化组件
                InitializeComponents(_options);
                
                // 设置控制台事件处理
                SetupConsoleHandlers();
                
                // 启动DNS服务
                if (StartDnsService(_options))
                {
                    _isRunning = true;
                    _logger?.LogStatus("DNS服务启动成功");
                    
                    // 等待关闭信号
                    WaitForShutdown();
                }
                else
                {
                    _logger?.LogError("DNS服务启动失败");
                    Environment.Exit(1);
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"启动DNS服务时发生严重错误: {ex.Message}");
                Environment.Exit(1);
            }
            finally
            {
                // 清理资源
                Cleanup();
                
                _logger?.LogStatus("DNS服务已停止");
                Console.WriteLine("=== DNS Service 已停止 ===");
            }
        }

        /// <summary>
        /// 解析命令行参数
        /// </summary>
        /// <param name="args">命令行参数数组</param>
        /// <returns>DNS服务选项</returns>
        private static DnsServiceOptions ParseCommandLineArgs(string[] args)
        {
            var options = new DnsServiceOptions();
            
            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i].ToLower())
                {
                    case "-p":
                    case "--port":
                        if (i + 1 < args.Length && int.TryParse(args[i + 1], out int port))
                        {
                            options.Port = port;
                            i++;
                        }
                        break;
                    case "-u":
                    case "--upstream":
                        if (i + 1 < args.Length)
                        {
                            options.UpstreamDnsServers = args[i + 1].Split(',').ToList();
                            i++;
                        }
                        break;
                    case "-r":
                    case "--records":
                        if (i + 1 < args.Length)
                        {
                            var records = args[i + 1].Split(';');
                            foreach (var record in records)
                            {
                                var parts = record.Split('=');
                                if (parts.Length == 2)
                                {
                                    options.DnsRecords[parts[0]] = parts[1];
                                }
                            }
                            i++;
                        }
                        break;
                    case "-c":
                    case "--config":
                        if (i + 1 < args.Length)
                        {
                            options.ConfigFile = args[i + 1];
                            i++;
                        }
                        break;
                    case "-l":
                    case "--log":
                        if (i + 1 < args.Length)
                        {
                            options.LogFile = args[i + 1];
                            i++;
                        }
                        break;
                    case "-h":
                    case "--help":
                        ShowHelp();
                        Environment.Exit(0);
                        break;
                }
            }
            
            return options;
        }

        /// <summary>
        /// 从配置文件加载配置
        /// </summary>
        /// <param name="configPath">配置文件路径</param>
        /// <param name="config">配置对象</param>
        private static void LoadConfigFromFile(string configPath, DnsServiceConfig config)
        {
            try
            {
                if (File.Exists(configPath))
                {
                    var json = File.ReadAllText(configPath);
                    var fileConfig = JsonSerializer.Deserialize<DnsServiceConfig>(json);
                    
                    if (fileConfig != null)
                    {
                        config.Port = fileConfig.Port;
                        config.UpstreamDnsServers = fileConfig.UpstreamDnsServers ?? config.UpstreamDnsServers;
                        
                        if (fileConfig.DnsCache != null)
                        {
                            foreach (var record in fileConfig.DnsCache)
                            {
                                config.DnsRecords[record.Key] = record.Value;
                            }
                        }
                    }
                    
                    Console.WriteLine($"已加载配置文件: {configPath}");
                }
                else
                {
                    Console.WriteLine($"配置文件不存在: {configPath}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"加载配置文件失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 显示帮助信息
        /// </summary>
        private static void ShowHelp()
        {
            Console.WriteLine("使用方法:");
            Console.WriteLine("  DnsService.exe [选项]");
            Console.WriteLine();
            Console.WriteLine("选项:");
            Console.WriteLine("  -p, --port <端口>        设置监听端口（默认: 153）");
            Console.WriteLine("  -u, --upstream <服务器>   设置上游DNS服务器，多个用逗号分隔");
            Console.WriteLine("                           默认: 8.8.8.8,114.114.114.114");
            Console.WriteLine("  -r, --records <记录>     设置自定义DNS记录，格式: domain=ip,domain2=ip2");
            Console.WriteLine("  -c, --config <文件>      从JSON配置文件加载设置");
            Console.WriteLine("  -h, --help              显示此帮助信息");
            Console.WriteLine();
            Console.WriteLine("示例:");
            Console.WriteLine("  DnsService.exe -p 153 -u 8.8.8.8,1.1.1.1");
            Console.WriteLine("  DnsService.exe -r \"example.com=192.168.1.1,test.com=10.0.0.1\"");
            Console.WriteLine("  DnsService.exe --config dns_config.json");
        }

        /// <summary>
        /// 初始化组件
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        private static void InitializeComponents(DnsServiceOptions options)
        {
            try
            {
                // 创建配置管理器
                _configManager = new DnsConfigManager();
                
                // 加载配置
                var config = _configManager.LoadConfig();
                
                // 应用命令行选项
                if (options.Port > 0)
                    config.Port = options.Port;
                
                if (options.UpstreamDnsServers != null && options.UpstreamDnsServers.Count > 0)
                    config.UpstreamDnsServers = options.UpstreamDnsServers;
                
                if (!string.IsNullOrEmpty(options.ConfigFile))
                    LoadConfigFromFile(options.ConfigFile, config);
                
                // 应用自定义DNS记录
                foreach (var record in options.DnsRecords)
                {
                    _configManager.AddDnsRecord(record.Key, record.Value);
                }
                
                // 创建日志记录器
                if (!string.IsNullOrEmpty(options.LogFile))
                {
                    var logWriter = File.CreateText(options.LogFile);
                    _logger = new ConsoleDnsLogger(logWriter, logWriter);
                }
                else
                {
                    _logger = new ConsoleDnsLogger();
                }
                
                // 创建DNS服务
                _dnsService = new LocalDnsService();
                _dnsService.SetLogger(_logger);
                
                // 设置DNS记录
                foreach (var record in config.DnsRecords)
                {
                    _dnsService.AddDnsRecord(record.Key, record.Value);
                }
                
                _logger.LogStatus("组件初始化完成");
            }
            catch (Exception ex)
            {
                throw new Exception($"初始化组件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 设置控制台事件处理
        /// </summary>
        private static void SetupConsoleHandlers()
        {
            try
            {
                _cancellationTokenSource = new CancellationTokenSource();
                
                // 设置Ctrl+C事件处理
                Console.CancelKeyPress += (sender, e) =>
                {
                    e.Cancel = true;
                    _logger?.LogStatus("收到停止信号，正在关闭服务...");
                    _cancellationTokenSource?.Cancel();
                };
                
                _logger?.LogStatus("控制台事件处理已设置");
            }
            catch (Exception ex)
            {
                throw new Exception($"设置控制台事件处理失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 启动DNS服务
        /// </summary>
        /// <param name="options">DNS服务选项</param>
        /// <returns>是否启动成功</returns>
        private static bool StartDnsService(DnsServiceOptions options)
        {
            try
            {
                if (_dnsService == null)
                {
                    _logger?.LogError("DNS服务未初始化");
                    return false;
                }
                
                var config = _configManager?.LoadConfig();
                if (config == null)
                {
                    _logger?.LogError("无法加载配置");
                    return false;
                }
                
                bool success = _dnsService.Start();
                if (success)
                {
                    _logger?.LogStatus($"DNS服务已启动，监听端口: {config.Port}");
                    return true;
                }
                else
                {
                    _logger?.LogError($"DNS服务启动失败，端口: {config.Port}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger?.LogError($"启动DNS服务时发生错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 等待关闭信号
        /// </summary>
        private static void WaitForShutdown()
        {
            try
            {
                _logger?.LogStatus("DNS服务正在运行，按Ctrl+C停止服务");
                
                // 等待取消令牌或关闭事件
                _shutdownEvent.WaitOne();
                
                if (_cancellationTokenSource != null)
                {
                    _cancellationTokenSource.Token.WaitHandle.WaitOne();
                }
                
                _logger?.LogStatus("收到关闭信号，正在停止服务...");
            }
            catch (Exception ex)
            {
                _logger?.LogError($"等待关闭信号时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清理资源
        /// </summary>
        private static void Cleanup()
        {
            try
            {
                _logger?.LogStatus("正在清理资源...");
                
                // 停止DNS服务
                _dnsService?.Stop();
                
                // 释放资源
                _dnsService?.Dispose();
                _logger?.Dispose();
                _configManager?.Dispose();
                _cancellationTokenSource?.Dispose();
                
                _logger?.LogStatus("资源清理完成");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"清理资源时发生错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 监听控制台输入
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        private static async Task ListenForConsoleInput(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    if (Console.KeyAvailable)
                    {
                        var key = Console.ReadKey(true);
                        if (key.Key == ConsoleKey.C && key.Modifiers == ConsoleModifiers.Control)
                        {
                            Console.WriteLine("\n收到停止信号，正在关闭服务...");
                            _cancellationTokenSource?.Cancel();
                            break;
                        }
                        else if (key.Key == ConsoleKey.S && key.Modifiers == ConsoleModifiers.Control)
                        {
                            Console.WriteLine("\n显示状态信息...");
                            ShowStatus();
                        }
                        else if (key.Key == ConsoleKey.H && key.Modifiers == ConsoleModifiers.Control)
                        {
                            Console.WriteLine("\n显示帮助信息...");
                            ShowHelp();
                        }
                    }
                    
                    await Task.Delay(100, cancellationToken);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
        }

        /// <summary>
        /// 等待退出信号
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        private static async Task WaitForExitSignal(CancellationToken cancellationToken)
        {
            try
            {
                await Task.Delay(Timeout.Infinite, cancellationToken);
            }
            catch (TaskCanceledException)
            {
                // 正常退出
            }
        }

        /// <summary>
        /// 显示服务状态
        /// </summary>
        private static void ShowStatus()
        {
            if (_dnsService != null)
            {
                Console.WriteLine($"服务状态: {(_isRunning ? "运行中" : "已停止")}");
                Console.WriteLine($"监听端口: {_dnsService.Port}");
                Console.WriteLine($"DNS缓存记录数: {_dnsService.DnsCache.Count}");
                Console.WriteLine($"运行时间: {DateTime.Now - Process.GetCurrentProcess().StartTime:hh\\:mm\\:ss}");
            }
        }

        /// <summary>
        /// DNS请求处理事件
        /// </summary>
        private static void OnDnsRequestProcessed(object? sender, Toolbox.DnsService.Events.DnsRequestEventArgs e)
        {
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] DNS请求: {e.Domain} -> {e.ResolvedIp} (来源: {e.SourceIp})");
        }

        /// <summary>
        /// 状态变化事件
        /// </summary>
        private static void OnStatusChanged(object? sender, Toolbox.DnsService.Events.DnsServiceStatusEventArgs e)
        {
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 状态: {e.Message} (成功: {e.IsSuccess})");
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        private static void StopService()
        {
            if (_isRunning && _dnsService != null)
            {
                Console.WriteLine("正在停止DNS服务...");
                _dnsService.Stop();
                _dnsService.Dispose();
                _isRunning = false;
                Console.WriteLine("DNS服务已停止");
            }
            
            _cancellationTokenSource?.Dispose();
        }
    }

    /// <summary>
    /// DNS服务命令行选项类
    /// 作者：huobing
    /// </summary>
    public class DnsServiceOptions
    {
        public int Port { get; set; } = 153;
        public List<string> UpstreamDnsServers { get; set; } = new();
        public Dictionary<string, string> DnsRecords { get; set; } = new();
        public string? ConfigFile { get; set; }
        public string? LogFile { get; set; }
    }
}